#include "common.h"

#define THREAD_NUM 4  //线程数量
#define SERVER_PORT 8888
#define SERVER_IP "127.0.0.1"
#define SAVE_DIR "./temp/client_file"
#define SEND_FILE_1 "./temp/client_file/tcp.txt"
#define SEND_FILE_2 "./temp/client_file/udp.txt"

int main(int argc, char* argv[]) 
{
    int client_socks[THREAD_NUM] = {-1, -1, -1, -1}; // 4个socket
    int ret = EXIT_FAILURE;
    pthread_t threads[THREAD_NUM];
    thread_arg_t thread_args[THREAD_NUM];
    
    if (argc != 1) 
    {
        fprintf(stderr, "Input error!\n");
        goto cleanup;
    }
    
    // 确保保存目录存在
    struct stat st = {0};
    if (stat(SAVE_DIR, &st) == -1) 
    {
        if (mkdir(SAVE_DIR, 0700) == -1) 
        {
            perror("mkdir error");
            goto cleanup;
        }
    }
    
    // 设置服务器地址和端口
    struct sockaddr_in server_addr = 
    {
        .sin_family = AF_INET,
        .sin_port = htons(SERVER_PORT),
        .sin_addr.s_addr = inet_addr(SERVER_IP) 
    };
    socklen_t server_addr_len = sizeof(server_addr);
    
    // 创建4个UDP socket，使用不同端口
    for (int i = 0; i < THREAD_NUM; i++) 
    {
        client_socks[i] = socket(AF_INET, SOCK_DGRAM, 0);
        if (client_socks[i] < 0) 
        {
            perror("client socket err");
            goto cleanup;
        }
        
        // 绑定到不同端口
        struct sockaddr_in client_addr = {
            .sin_family = AF_INET,
            .sin_port = htons(9000 + i), // 使用不同端口
            .sin_addr.s_addr = INADDR_ANY
        };
        
        if (bind(client_socks[i], (struct sockaddr*)&client_addr, sizeof(client_addr)) < 0) 
        {
            perror("bind error");
            goto cleanup;
        }
        
        printf("UDP socket %d created on port %d\n", i + 1, ntohs(client_addr.sin_port));
    }
    
    // 设置线程参数并创建线程
    // 前两个线程用于发送文件
    for (int i = 0; i < 2; i++) 
    {
        // 先通知服务器要发送文件
        char type = mTRANSFER_TYPE_SEND;
        if (sendto(client_socks[i], &type, 1, 0, 
                  (struct sockaddr*)&server_addr, server_addr_len) <= 0) 
        {
            perror("send type error");
            goto cleanup;
        }
        
        thread_args[i].msockfd = client_socks[i];
        thread_args[i].mIs_send = 1;
        thread_args[i].msave_dir = NULL;
        thread_args[i].mfilepath = (i == 0) ? SEND_FILE_1 : SEND_FILE_2;
        memcpy(&thread_args[i].maddr, &server_addr, server_addr_len);
        thread_args[i].maddr_len = server_addr_len;
        
        if (pthread_create(&threads[i], NULL, file_transfer_thread, &thread_args[i]) != 0) 
        {
            perror("pthread_create error");
            goto cleanup;
        }
    }
    
    // 后两个线程用于接收文件
    for (int i = 2; i < 4; i++) 
    {
        // 先通知服务器要接收文件
        char type = mTRANSFER_TYPE_RECEIVE; 
        if (sendto(client_socks[i], &type, 1, 0, 
                  (struct sockaddr*)&server_addr, server_addr_len) <= 0) 
        {
            perror("send type error");
            goto cleanup;
        }
        
        thread_args[i].msockfd = client_socks[i];
        thread_args[i].mIs_send = 0;
        thread_args[i].msave_dir = SAVE_DIR;
        thread_args[i].mfilepath = NULL;
        memcpy(&thread_args[i].maddr, &server_addr, server_addr_len);
        thread_args[i].maddr_len = server_addr_len;
        
        if (pthread_create(&threads[i], NULL, file_transfer_thread, &thread_args[i]) != 0) 
        {
            perror("pthread_create error");
            goto cleanup;
        }
    }
    
    // 等待所有线程完成
    for (int i = 0; i < THREAD_NUM; i++) 
    {
        pthread_join(threads[i], NULL);
    }
    
    ret = EXIT_SUCCESS; // 成功

cleanup:
    for (int i = 0; i < 4; i++) 
    {
        if (client_socks[i] != -1) 
        {
            close(client_socks[i]);
        }
    }
    return ret;
}